/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.utils;

//import org.eclipse.emf.common.util.Enumerator;
import org.eclipse.emf.common.util.Enumerator;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.graphics.Image;
import org.eclipse.uml2.uml.ClassifierTemplateParameter;
import org.eclipse.uml2.uml.Comment;
import org.eclipse.uml2.uml.ConnectableElementTemplateParameter;
import org.eclipse.uml2.uml.Connector;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.Generalization;
import org.eclipse.uml2.uml.LiteralSpecification;
import org.eclipse.uml2.uml.Message;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.OperationTemplateParameter;
import org.eclipse.uml2.uml.PackageImport;
import org.eclipse.uml2.uml.Parameter;
import org.eclipse.uml2.uml.ProfileApplication;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Pseudostate;
import org.eclipse.uml2.uml.RedefinableTemplateSignature;
import org.eclipse.uml2.uml.Slot;
import org.eclipse.uml2.uml.TemplateBinding;
import org.eclipse.uml2.uml.TemplateParameter;
import org.eclipse.uml2.uml.TemplateParameterSubstitution;
import org.eclipse.uml2.uml.TemplateSignature;
import org.eclipse.uml2.uml.Transition;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.editpart.IUMLDiagramElementEditPart;
import com.cea.papyrus.core.editpart.IUMLElementEditPart;
import com.cea.papyrus.core.editpart.IUMLObjectEditPart;

/**
 * This class handles title label for tabbed properties.
 * 
 * @author Chokri Mraidha
 */
public class UMLObjectLabelProvider
extends org.eclipse.jface.viewers.LabelProvider {

	/**
	 * 
	 */
	static final String default_label = "undefined";
	
	/**
	 * 
	 */
	static final Image default_img = PapyrusPlugin.getImage(PapyrusPlugin.DEFAULT_IMAGE);

	/**
	 * 
	 * 
	 * @param obj 
	 * 
	 * @return 
	 * 
	 * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
	 */
	@Override
	public Image getImage(Object obj) {

		if ((obj == null) || obj.equals(StructuredSelection.EMPTY)) {
			return default_img;
		}		

		Object object;		
		// Retrieve element or first element if multiple
		if (obj instanceof StructuredSelection) {
			object = ((StructuredSelection)obj).getFirstElement();
		} else {
			object = obj;
		}

		// Should be an IUMLObjectEditPart --> either IUMLDiagramElementEditPart || IUMLElementEditPart
		if (!(object instanceof IUMLObjectEditPart)) {
			return default_img;
		}

		String typeName = "unknown";

		// Case IUMLDiagramElementEditPart
		if (object instanceof IUMLDiagramElementEditPart) {
			typeName		= "Diagram_"+((IUMLDiagramElementEditPart) object).getDiagram().getType();
		}

		// Case IUMLElementEditPart		
		else if (object instanceof IUMLElementEditPart) {
			Element element	= ((IUMLElementEditPart) object).getUmlElement();
			if(element != null) {
				return getImage(element);
			}
		}

		String imageName = PapyrusPlugin.UML_ICONS_16x16+typeName+".gif";	
		Image image 	 = PapyrusPlugin.getImage(imageName); // return null or DEFAULT_IMAGE
		
		return image;	
	}
	
	/**
	 * 
	 * 
	 * @param element 
	 * 
	 * @return 
	 */
	public Image getImage(Element element) {
		String typeName = "unknown";
		if (element == null) {
			return default_img;	
		}
		
		// Special cases
		if (element instanceof LiteralSpecification) {
			typeName = "EnumerationLiteral";

		} else if (element instanceof Parameter) {
			Parameter param = (Parameter) element;
			typeName = "Parameter_"+param.getDirection().getLiteral();

		} else if (element instanceof Pseudostate) {
			Pseudostate ps = (Pseudostate) element;
			typeName = "Pseudostate_"+ps.getKind().getLiteral();

		} else if (element instanceof Message) {
			Message msg = (Message) element;
			typeName = "Message_"+msg.getMessageSort().getLiteral();

		} else if (element instanceof Connector) {
			Connector cnr = (Connector) element;
			typeName = "Connector_"+cnr.getKind().getLiteral();

		}  else if (element instanceof Transition) {
			Transition trans = (Transition) element;
			typeName = "Transition_"+trans.getKind().getLiteral();

		} 

		// Default case
		else {
			typeName = element.getClass().getSimpleName();
			// Uml type are suffixed by Impl (ex: TypeImpl)
			typeName = typeName.replace("Impl", "");	
		}
		
		String imageName = PapyrusPlugin.UML_ICONS_16x16+typeName+".gif";	
		Image image 	 = PapyrusPlugin.getImage(imageName); // return null or DEFAULT_IMAGE
		return image;
	}

	/**
	 * 
	 * 
	 * @param kind 
	 * @param diagType 	 * @param clazz 
	 * 
	 * @return 
	 */
	public Image getImage(Class clazz, Object kind) {

		if (kind == null) {
			return getImage(clazz, null);
			
		} else if (kind instanceof Enumerator) {
			return getImage(clazz, ((Enumerator) kind).getLiteral());
			
		} else if (kind instanceof String) {
			return getImage(clazz, (String) kind);
			
		} else {
			return getImage(clazz, null);
		}
	}
		
	/**
	 * 
	 * 
	 * @param kind 
	 * @param diagType 	 * @param clazz 
	 * 
	 * @return 
	 */
	private Image getImage(Class clazz, String kind) {

		if (clazz == null) {
			return default_img;
		}

		String typeName = clazz.getSimpleName();

		if(typeName.equals("Diagram") && (kind != null)){
			typeName = "Diagram_" + kind;
		}
		else if(typeName.equals("Parameter") && (kind != null)){
			typeName = "Parameter_" + kind;
		} 
		else if(typeName.equals("Pseudostate") && (kind != null)){
			typeName = "Pseudostate_" + kind;
		}
		else if (typeName.equals("Choice")){
			typeName = "Pseudostate_choice";
		}
		else if (typeName.equals("DeepHistory")){
			typeName = "Pseudostate_deepHistory";
		}
		else if (typeName.equals("EntryPoint")){
			typeName = "Pseudostate_entryPoint";
		}
		else if (typeName.equals("ExitPoint")){
			typeName = "Pseudostate_exitPoint";
		}
		else if (typeName.equals("Fork")){
			typeName = "Pseudostate_fork";
		}
		else if (typeName.equals("Initial")){
			typeName = "Pseudostate_initial";
		}
		else if (typeName.equals("Join")){
			typeName = "Pseudostate_join";
		}
		else if (typeName.equals("Junction")){
			typeName = "Pseudostate_junction";
		}
		else if (typeName.equals("ShallowHistory")){
			typeName = "Pseudostate_shallowHistory";
		}
		else if (typeName.equals("Terminate")){
			typeName = "Pseudostate_terminate";
		}
		else if (typeName.equals("Horizontal")){
			typeName = "Region_horizontal";
		}
		else if (typeName.equals("Vertical")){
			typeName = "Region_vertical";
		}
		else if (typeName.equals("Message") && (kind != null)){
			typeName = "Message_"+kind;
		} 
		else if (typeName.equals("Connector") && (kind != null)){
			typeName = "Connector_"+kind;
		}
		else if (typeName.equals("Transition") && (kind != null)){
			typeName = "Transition_"+kind;
		}
			
		String imageName = PapyrusPlugin.UML_ICONS_16x16+typeName+".gif";	
		Image image 	 = PapyrusPlugin.getImage(imageName); // return null or DEFAULT_IMAGE

		return image;	
	}

	/**
	 * 
	 * 
	 * @param obj 
	 * 
	 * @return 
	 * 
	 * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
	 */
	@Override
	public String getText(Object obj) {

		if ((obj == null) || obj.equals(StructuredSelection.EMPTY)) {
			return default_label;
		}

		Object object;		
		// Retrieve element or first element if multiple
		if (obj instanceof StructuredSelection) {
			object = ((StructuredSelection)obj).getFirstElement();
		} else {
			object = obj;
		}

		// Should be an IUMLObjectEditPart --> either IUMLDiagramElementEditPart || IUMLElementEditPart
		if (!(object instanceof IUMLObjectEditPart)) {
			return default_label;
		}

		String label = default_label;

		// Case IUMLDiagramElementEditPart
		if (object instanceof IUMLDiagramElementEditPart) {
			label	= ((IUMLDiagramElementEditPart) object).getDiagram().getName();
		} else if (object instanceof IUMLElementEditPart) {
			label	= getText((IUMLElementEditPart) object, false);
		}

		return label;
	}

	/**
	 * Give text for uml elements only.
	 * 
	 * @param useShortLabel 
	 * @param element 	 * @param elementEditPart 
	 * 
	 * @return 
	 */
	protected String getText(IUMLElementEditPart elementEditPart, boolean useShortLabel) {
		String label = default_label;
		Element element = elementEditPart.getUmlElement();

		label = getText(element, useShortLabel);

		return label;	
	}

	/**
	 * Give text for uml elements only.
	 * 
	 * @param useShortLabel 
	 * @param element 
	 * 
	 * @return 
	 */
	public String getText(Element element, boolean useShortLabel) {
		String label = default_label;

		// Not a diagram element != null
		if (element instanceof ClassifierTemplateParameter) {
			TemplateSignature signature = ((TemplateParameter)element).getSignature() ;
			NamedElement owner = (NamedElement)signature.getOwner() ;
			label = "Classifier template parameter (in signature of  " + owner.getQualifiedName() + ")";
		}
		else if (element instanceof OperationTemplateParameter) {
			TemplateSignature signature = ((TemplateParameter)element).getSignature() ;
			NamedElement owner = (NamedElement)signature.getOwner() ;
			label = "Operation template parameter (in signature of  " + owner.getQualifiedName() + ")";				
		}
		else if (element instanceof ConnectableElementTemplateParameter) {
			TemplateSignature signature = ((TemplateParameter)element).getSignature() ;
			NamedElement owner = (NamedElement)signature.getOwner() ;
			label = "Connectable element template parameter (in signature of  " + owner.getQualifiedName() + ")";				
		}
		else if (element instanceof TemplateParameter) {
			TemplateSignature signature = ((TemplateParameter)element).getSignature() ;
			NamedElement owner = (NamedElement)signature.getOwner() ;
			label = "Template parameter (in signature of  " + owner.getQualifiedName() + ")";				
		}
		else if (element instanceof RedefinableTemplateSignature) {
			NamedElement owner = (NamedElement)((RedefinableTemplateSignature)element).getOwner() ;
			label = "Redefinable template signature (for " + owner.getQualifiedName() + ")";				
		}
		else if (element instanceof TemplateSignature) {
			NamedElement owner = (NamedElement)((TemplateSignature)element).getOwner() ;
			label = "Template signature (for " + owner.getQualifiedName() + ")";				
		}
		else if (element instanceof TemplateBinding) {
			NamedElement owner = (NamedElement)((TemplateBinding)element).getOwner() ;
			label = "Template binding (for " + owner.getQualifiedName() + ")";
		}
		else if (element instanceof TemplateParameterSubstitution) {
			TemplateParameter tp = ((TemplateParameterSubstitution)element).getFormal() ;
			if (tp != null) {
				NamedElement formalParameter = (NamedElement)tp.getParameteredElement() ;
				label = "Template parameter substition (for parameter " + formalParameter.getName()+ " )";
			}
		}
		else if (element instanceof Property) {
			if (useShortLabel) {
				com.cea.papyrus.umlutils.Property prop = new com.cea.papyrus.umlutils.Property((Property) element);
				// getShortLabel without visibility sign
				label = prop.getShortLabel(false);
			} else {
				label = ((Property) element).getQualifiedName();				
			}
		} else if (element instanceof Slot){
			if (useShortLabel) {
				com.cea.papyrus.umlutils.Slot slot = new com.cea.papyrus.umlutils.Slot((Slot) element);
				label = slot.getLabel();
			} else {
				if(((Slot)element).getDefiningFeature()!=null)
					label = ((Slot) element).getDefiningFeature().getQualifiedName();
				else
					label = "UndefinedSlot";
			}
		} else if (element instanceof Parameter) {
			if (useShortLabel) {
				com.cea.papyrus.umlutils.Parameter param = new com.cea.papyrus.umlutils.Parameter((Parameter) element);
				label = param.getLabel();
			} else {
				label = ((Parameter) element).getQualifiedName();				
			}
		} else if (element instanceof NamedElement) {
			if (useShortLabel) {
				label = ((NamedElement) element).getName();
			} else {
				label = ((NamedElement) element).getQualifiedName();				
			}

		} else if (element instanceof PackageImport) {			
			if (((PackageImport) element).getImportedPackage() != null) {
				label = "import "+((PackageImport) element).getImportedPackage().getName();
			}

		} else if (element instanceof ElementImport) {			
			if (((ElementImport) element).getImportedElement() != null) {
				label = "import "+((ElementImport) element).getImportedElement().getName();
			}

		} else if (element instanceof Comment) {
			if (((Comment) element).getBody() != null) {
				label = ((Comment) element).getBody();

				if (label.length() >= 10) {
					label = label.substring(0, 9)+"...";
				}

				if (label.indexOf('\n') > 0) {
					label = label.substring(0, label.indexOf('\n'))+"...";
				}
			}

		} else if (element instanceof Generalization) {			
			String superclass = "unknown";
			if (((Generalization) element).getGeneral() != null) {
				superclass = ((Generalization) element).getGeneral().getName();			
			}
			label = "is a "+superclass;

		} else if (element instanceof ProfileApplication) {			
			String appliedProfile = "unknown";		
			if (((ProfileApplication) element).getAppliedProfile() != null) {
				appliedProfile = ((ProfileApplication) element).getAppliedProfile().getName();			
			}			
			label = "Applied "+appliedProfile+" profile";

		} else if (element instanceof Element) { // Test Element in last position		
			label = (element).toString();
			
		} // else undefined
		
		if (label == null) {
			label = default_label;
		}

		return label;	
	}
}